
#include "tinyrpc/base/Fd.h"
#include <memory>
#include "serversocketchannel.h"
#include <sys/types.h>        
#include <sys/socket.h>
#include<netinet/in.h>
#include "../coroutine_function.h"
#include <unistd.h>
#include <fcntl.h>
#include <tinyrpc/base/logger/logger.h>
namespace TinyRPC{

ServerSocketChannel ServerSocketChannel::CreateAndBind(INetAddress & address){
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(server_fd < 0){
        LOG_ERROR<<"server socket create error";
        exit(0);
    }
    struct sockaddr_in  addr = address.getSockAddr();
    socklen_t addr_len = sizeof(addr);
    int rt = bind(server_fd, (const struct sockaddr *)&addr, addr_len);
    if(rt < 0){
        LOG_ERROR<<"server socket bind error";
        exit(0);
    }
    return ServerSocketChannel(server_fd,  address);
}
SocketChannelPtr ServerSocketChannel::accept(){
     
    struct sockaddr_in  addr;
    socklen_t addr_len;

    int clientfd = coroutine_accept(m_fd->fd(), (sockaddr *)&addr, &addr_len);
    if(clientfd < 0){
        LOG_ERROR<<"server socket accept error";
        exit(0);
    }
    return std::make_shared<SocketChannel>(clientfd, INetAddress(addr)) ;
}
int ServerSocketChannel::listen(){
    return ::listen(m_fd->fd(), 128);
}

// 设置为非阻塞模式
ServerSocketChannel::ServerSocketChannel(int fd, INetAddress & address)
: AbstractChannel(fd)
, m_localAddress(address)
{
   
    ::fcntl(m_fd->fd(), F_SETFL, O_NONBLOCK);

    int opt_val = 1;
    ::setsockopt(m_fd->fd(), SOL_SOCKET, SO_REUSEPORT, &opt_val, sizeof(opt_val));
}

}


